#ifndef _CCBONE_H_
#define _CCBONE_H_

#include "cocos2d.h"
#include "CCSpineObject.h"

NS_CC_BEGIN

class CCSlot;
class CCSkeletalSprite;

/**
 * bone
 */

class CCBone : public CCSpineObject {
public:
	/// bone pointer list
	typedef vector<CCBone*> BonePtrList;
    typedef vector<CCSlot*> SlotPtrList;
	
    // bone transform attribute
    
    struct State {
        /// x offset
		float x;
		
		/// y offset
		float y;
		
		/// rotation in degree, positive value means counter-clockwise, x axis is zero degree
		float rotation;
		
		/// x scale
		float scaleX;
		
		/// y scale
		float scaleY;
        
        CCAffineTransform transform;
    };
    
    /// flags of bone
    enum Flag {
        /// bone position is fixed
        FIXED_POSITION = 0x1,
        
        /// bone rotation angle is fixed
        FIXED_ROTATION = 0x2,
        
        /// bone scale is fixed
        FIXED_SCALE = 0x4
    };
	
private:
	/// parent bone
	CCBone* m_parent;

	/// bone length
	float m_length;
	
	/// current state
	State m_originalState;
	
	/// child bones
	BonePtrList m_children;
    
    // child slot
    SlotPtrList m_slotList;

    /// flags
    int m_flags;
	
	/// state map
	typedef map<CCSkeletalSprite*, State> StateMap;
	StateMap m_stateMap;

protected:
	CCBone();
	
	/// set parent
	void setParent(CCBone* parent) { m_parent = parent; }

public:
	virtual ~CCBone();

	/**
	 * create a bone class
	 *
	 * @param parent parent bone, or NULL if no parent
	 */
	static CCBone* create();
	
	/// add child bone
	void addChild(CCBone* bone);
	
	/// get children bone list
	BonePtrList& getChildren() { return m_children; }
    
    void addSlot(CCSlot* slot);
    
    SlotPtrList& getSlotList() { return m_slotList; }

	/// get parent bone
	CCBone* getParent() { return m_parent; }

	/// set length
	void setLength(float len) { m_length = len; }

	/// get length
	float getLength() { return m_length; }
	
	/// get bone state for an owner
	State& getState(CCSkeletalSprite* owner);
    
    void nodeToParentTransform(State& state);
	
	/// remove state for an owner
	void clearState(CCSkeletalSprite* owner);

	/// get original x offset
	State& getOriginalState() { return m_originalState; }

    /// add a flag
    void addFlag(Flag f) { m_flags |= f; }

    /// remove a flag
    void removeFlag(Flag f) { m_flags &= ~f; }

    /// get flag
    int getFlags() { return m_flags; }

    /// clear flags
    void clearFlags() { m_flags = 0; }

    /// has flag?
    bool hasFlag(Flag f) { return (m_flags & f) != 0; }
};

NS_CC_END

#endif // __CCBone_h__
